home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / g_quake / dropde-2.zip / COMBAT.QC < prev    next >
Text File  |  1996-09-04  |  7KB  |  328 lines

  1.  
  2. void() T_MissileTouch;
  3. void() info_player_start;
  4. void(entity targ, entity attacker) ClientObituary;
  5.  
  6. void() monster_death_use;
  7.  
  8. //============================================================================
  9.  
  10. /*
  11. ============
  12. CanDamage
  13.  
  14. Returns true if the inflictor can directly damage the target.  Used for
  15. explosions and melee attacks.
  16. ============
  17. */
  18. float(entity targ, entity inflictor) CanDamage =
  19. {
  20. // bmodels need special checking because their origin is 0,0,0
  21.     if (targ.movetype == MOVETYPE_PUSH)
  22.     {
  23.         traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self);
  24.         if (trace_fraction == 1)
  25.             return TRUE;
  26.         if (trace_ent == targ)
  27.             return TRUE;
  28.         return FALSE;
  29.     }
  30.     
  31.     traceline(inflictor.origin, targ.origin, TRUE, self);
  32.     if (trace_fraction == 1)
  33.         return TRUE;
  34.     traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self);
  35.     if (trace_fraction == 1)
  36.         return TRUE;
  37.     traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self);
  38.     if (trace_fraction == 1)
  39.         return TRUE;
  40.     traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self);
  41.     if (trace_fraction == 1)
  42.         return TRUE;
  43.     traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self);
  44.     if (trace_fraction == 1)
  45.         return TRUE;
  46.  
  47.     return FALSE;
  48. };
  49.  
  50.  
  51. /*
  52. ============
  53. Killed
  54. ============
  55. */
  56. void(entity targ, entity attacker) Killed =
  57. {
  58.     local entity oself;
  59.  
  60.     oself = self;
  61.     self = targ;
  62.     
  63.     if (self.health < -99)
  64.         self.health = -99;        // don't let sbar look bad if a player
  65.  
  66.     if (self.movetype == MOVETYPE_PUSH || self.movetype == MOVETYPE_NONE)
  67.     {    // doors, triggers, etc
  68.         self.th_die ();
  69.         self = oself;
  70.         return;
  71.     }
  72.  
  73.     self.enemy = attacker;
  74.  
  75.     if (self.deadflag == DEAD_NO)
  76.     {
  77.         // bump the monster counter
  78.         if (self.flags & FL_MONSTER)
  79.         {
  80.             killed_monsters = killed_monsters + 1;
  81.             WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
  82.         }
  83.  
  84.         ClientObituary(self, attacker);
  85.     
  86.         self.takedamage = DAMAGE_NO;
  87.         self.touch = SUB_Null;
  88.     }
  89.  
  90.     monster_death_use();
  91.     self.th_die ();
  92.     
  93.     self = oself;
  94. };
  95.  
  96.  
  97. /*
  98. ============
  99. T_Damage
  100.  
  101. The damage is coming from inflictor, but get mad at attacker
  102. This should be the only function that ever reduces health.
  103. ============
  104. */
  105. void(entity targ, entity inflictor, entity attacker, float damage) T_Damage=
  106. {
  107.     local    vector    dir;
  108.     local    entity    oldself;
  109.     local    float    save;
  110.     local    float    take;
  111.  
  112.     if (!targ.takedamage)
  113.         return;
  114.  
  115. // used by buttons and triggers to set activator for target firing
  116.     damage_attacker = attacker;
  117.  
  118. // check for quad damage powerup on the attacker
  119.     if (attacker.super_damage_finished > time)
  120.         damage = damage * 4;
  121.  
  122. // save damage based on the target's armor level
  123.  
  124.     save = ceil(targ.armortype*damage);
  125.     if (save >= targ.armorvalue)
  126.     {
  127.         save = targ.armorvalue;
  128.         targ.armortype = 0;    // lost all armor
  129.         targ.items = targ.items - (targ.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3));
  130.     }
  131.     
  132.     targ.armorvalue = targ.armorvalue - save;
  133.     take = ceil(damage-save);
  134.  
  135. // add to the damage total for clients, which will be sent as a single
  136. // message at the end of the frame
  137. // FIXME: remove after combining shotgun blasts?
  138.     if (targ.flags & FL_CLIENT)
  139.     {
  140.         targ.dmg_take = targ.dmg_take + take;
  141.         targ.dmg_save = targ.dmg_save + save;
  142.         targ.dmg_inflictor = inflictor;
  143.     }
  144.  
  145. // figure momentum add
  146.     if ( (inflictor != world) && (targ.movetype == MOVETYPE_WALK) )
  147.     {
  148.         dir = targ.origin - (inflictor.absmin + inflictor.absmax) * 0.5;
  149.         dir = normalize(dir);
  150.         targ.velocity = targ.velocity + dir*damage*8;
  151.     }
  152.  
  153. // check for godmode or invincibility
  154.     if (targ.flags & FL_GODMODE)
  155.         return;
  156.     if (targ.invincible_finished >= time)
  157.     {
  158.         if (self.invincible_sound < time)
  159.         {
  160.             sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
  161.             self.invincible_sound = time + 2;
  162.         }
  163.         return;
  164.     }
  165.  
  166.     // Avoid damaging teammate but not self.
  167.     // Note that in a game of tag (teamplay < 0), everyone can be
  168.     // hurt.
  169.     if (teamplay > 0)
  170.         if (targ != attacker)
  171.             if (targ.start_team > 0 && targ.start_team == attacker.start_team)
  172.                 return;
  173.         
  174. // do the damage
  175.     targ.health = targ.health - take;
  176.             
  177.     if (targ.health <= 0)
  178.     {
  179.         Killed (targ, attacker);
  180.         return;
  181.     }
  182.  
  183. // react to the damage
  184.     oldself = self;
  185.     self = targ;
  186.  
  187.     if ( (self.flags & FL_MONSTER) && attacker != world)
  188.     {
  189.     // get mad unless of the same class (except for soldiers)
  190.         if (self != attacker && attacker != self.enemy)
  191.         {
  192.             if ( (self.classname != attacker.classname) 
  193.             || (self.classname == "monster_army" ) )
  194.             {
  195.                 if (self.enemy.classname == "player")
  196.                     self.oldenemy = self.enemy;
  197.                 self.enemy = attacker;
  198.                 FoundTarget ();
  199.             }
  200.         }
  201.     }
  202.  
  203.     if (self.th_pain)
  204.     {
  205.         self.th_pain (attacker, take);
  206.     // nightmare mode monsters don't go into pain frames often
  207.         if (skill == 3)
  208.             self.pain_finished = time + 5;        
  209.     }
  210.  
  211.     self = oldself;
  212. };
  213.  
  214. /*
  215. ============
  216. T_RadiusDamage
  217. ============
  218. */
  219. void(entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage =
  220. {
  221.     local    float     points;
  222.     local    entity    head;
  223.     local    vector    org;
  224.  
  225.     head = findradius(inflictor.origin, damage+40);
  226.     
  227.     while (head)
  228.     {
  229.         if (head != ignore)
  230.         {
  231.             if (head.takedamage)
  232.             {
  233.                 org = head.origin + (head.mins + head.maxs)*0.5;
  234.                 points = 0.5*vlen (inflictor.origin - org);
  235.                 if (points < 0)
  236.                     points = 0;
  237.                 points = damage - points;
  238.                 if (head == attacker)
  239.                     points = points * 0.5;
  240.                 if (points > 0)
  241.                 {
  242.                     if (CanDamage (head, inflictor))
  243.                     {    // shambler takes half damage from all explosions
  244.                         if (head.classname == "monster_shambler")                        
  245.                             T_Damage (head, inflictor, attacker, points*0.5);
  246.                         else
  247.                             T_Damage (head, inflictor, attacker, points);
  248.                     }
  249.                 }
  250.             }
  251.         }
  252.         head = head.chain;
  253.     }
  254. };
  255.  
  256. /* Added for thunderbolt water shock damage.
  257. ============
  258. T_WaterRadiusDamage
  259. ============
  260. */
  261. void(entity inflictor, entity attacker, float damage, float radius
  262.         , entity ignore) T_WaterRadiusDamage =
  263. {
  264.     local    entity    head;
  265.     local    vector    org;
  266.  
  267.   head = findradius(inflictor.origin, radius);
  268.  
  269.     while (head)
  270.     {
  271.         if (head != ignore)
  272.         {
  273.       if (head.takedamage && head.waterlevel)
  274.             {
  275.                 local float dam;
  276.                 dam = ((radius - vlen(inflictor.origin - head.origin)) / 10) * damage;
  277.                 if (dam < 0)
  278.                     dam = 0;
  279.                 else if (head.classname == "monster_shambler")
  280.                     dam = dam * 0.5;
  281.                 if (dam && CanDamage (head, inflictor))
  282.                 {
  283.                     head.effects = head.effects | EF_MUZZLEFLASH;
  284.                     T_Damage (head, inflictor, attacker, dam);
  285.                 }
  286.             }
  287.         }
  288.         head = head.chain;
  289.     }
  290. };
  291.  
  292. /*
  293. ============
  294. T_BeamDamage
  295. ============
  296. */
  297. void(entity attacker, float damage) T_BeamDamage =
  298. {
  299.     local    float     points;
  300.     local    entity    head;
  301.     
  302.     head = findradius(attacker.origin, damage+40);
  303.     
  304.     while (head)
  305.     {
  306.         if (head.takedamage)
  307.         {
  308.             points = 0.5*vlen (attacker.origin - head.origin);
  309.             if (points < 0)
  310.                 points = 0;
  311.             points = damage - points;
  312.             if (head == attacker)
  313.                 points = points * 0.5;
  314.             if (points > 0)
  315.             {
  316.                 if (CanDamage (head, attacker))
  317.                 {
  318.                     if (head.classname == "monster_shambler")                        
  319.                         T_Damage (head, attacker, attacker, points*0.5);
  320.                     else
  321.                         T_Damage (head, attacker, attacker, points);
  322.                 }
  323.             }
  324.         }
  325.         head = head.chain;
  326.     }
  327. };
  328.